/**
 * elLaunch
 *
 * @version $Id: ellaunch-service.js 19 2008-11-26 07:22:09Z ayunyan $
 * @author ayunyan <ayu@commun.jp>
 */
const CONTRACTID = "@ayu.commun.jp/ellaunch-service;1";
const CLASSNAME = 'elLaunchService';
const CID = Components.ID("{e41d39fe-c163-11dc-8133-0090cccaecea}");

function alert(msg) {
    Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService).alert(null, "Alert", msg);
}
var consoleService = Components.classes['@mozilla.org/consoleservice;1'].getService(Components.interfaces.nsIConsoleService);

var elLaunchService = {
    prefService: null,
    observerService: null,
    gamesList: [],
    QueryInterface: function(aIID)
    {
        if (!aIID.equals(Components.interfaces.nsIContentPolicy) &&
          !aIID.equals(Components.interfaces.nsISupportsWeakReference) &&
          !aIID.equals(Components.interfaces.nsISupports) &&
          !aIID.equals(Components.interfaces.nsIObserver)) {
            throw Components.results.NS_ERROR_NO_INTERFACE;
        }
        return this;
    },
    observe: function(aSubject, aTopic, aData)
    {
        if (aTopic == "app-startup") {
            this.observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
            this.observerService.addObserver(this, "final-ui-startup", false);

            this.prefService = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService);
            this.prefService.QueryInterface(Components.interfaces.nsIPrefBranch2);
            this.prefService.addObserver("extensions.ellaunch.games", this, false);
        } else if (aTopic == "final-ui-startup") {
            this.observerService.removeObserver(this, "final-ui-startup");
            this.gamesList = new Array();
            try {
                var data = this.prefService.getComplexValue('extensions.ellaunch.games', Components.interfaces.nsISupportsString).data;
                data = data.split(',');
                for (var i = 0; i < data.length; i++) {
                    this.gamesList[data[i]] = 1;
                }
            } catch (e) {
                this.gamesList = [];
            }
        } else if (aTopic == "quit-application") {
            this.observerService.removeObserver(this, "quit-application");
            this.prefService.removeObserver("extensions.ellaunch.games", this);
        } else if (aTopic == "nsPref:changed") {
            this.gamesList = new Array();
            try {
                var data = this.prefService.getComplexValue('extensions.ellaunch.games', Components.interfaces.nsISupportsString).data;
                data = data.split(',');
                for (var i = 0; i < data.length; i++) {
                    this.gamesList[data[i]] = 1;
                }
            } catch (e) {
                this.gamesList = [];
            }
        }
    },
    shouldLoad: function(aContentType, aContentLocation, aRequestOrigin, aContext, aMimeTypeGuess, aExtra)
    {
        if (aContentType != Components.interfaces.nsIContentPolicy.TYPE_DOCUMENT) return Components.interfaces.nsIContentPolicy.ACCEPT;

        if ((aContentLocation.scheme in this.gamesList)) {
            this.observerService.notifyObservers(null, "ellaunch-launch-request", aContentLocation.spec);
            return Components.interfaces.nsIContentPolicy.REJECT_REQUEST;
        }


        var hookGameTracker = false;
        var hookGyaASE = false;
        var prefManager = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
        try {
            hookGameTracker = prefManager.getBoolPref("extensions.ellaunch.hook_gametracker");
        } catch (e) {
            hookGameTracker = false;
        }

        try {
            hookGyaASE = prefManager.getBoolPref("extensions.ellaunch.hook_gyaase");
        } catch (e) {
            hookGyaASE = false;
        }

        if (hookGameTracker && aContentLocation.scheme == 'gsc') {
            var params = this.parseGSCURL(aContentLocation.spec);
            if (!params || params['action'] != 'joinGame') return Components.interfaces.nsIContentPolicy.ACCEPT;
            if (!params['game'] in this.gamesList) return Components.interfaces.nsIContentPolicy.ACCEPT;
            var url = params['game'] + '://' + params['ip'] + ':' + params['port'];
            this.observerService.notifyObservers(null, "ellaunch-launch-request", url);
            return Components.interfaces.nsIContentPolicy.REJECT_REQUEST;
        }

        if (hookGyaASE && aContentLocation.spec.substring(0, 36) == 'http://d3.jpn.org/gyaase/launch.php/') {
            var rawurl = aContentLocation.spec.substring(36, aContentLocation.spec.length - 4);

            if (rawurl.length == 0 || (pos = rawurl.indexOf("://")) == -1) return Components.interfaces.nsIContentPolicy.ACCEPT;

            var game_type = rawurl.substring(0, pos);

            if (!game_type in this.gamesList) return Components.interfaces.nsIContentPolicy.ACCEPT;

            this.observerService.notifyObservers(null, "ellaunch-launch-request", rawurl);
            return Components.interfaces.nsIContentPolicy.REJECT_REQUEST;
        }
        return Components.interfaces.nsIContentPolicy.ACCEPT;
    },
    shouldProcess: function(aContentType, aContentLocation, aRequestOrigin, aContext, aMimeTypeGuess, aExtra)
    {
        return Components.interfaces.nsIContentPolicy.ACCEPT;
    },
    parseGSCURL: function(url)
    {
        // gsc://action:name=value&n2=v2
        var params = {};
        var sep = url.indexOf(':', 5);
        if (sep == -1) return false;
        params['action'] = url.substr(6, sep - 6);
        var query = url.substr(sep + 1).split("&");
        for (var i = 0; i < query.length; i++) {
            var kv = query[i].split('=');
            params[kv[0]] = kv[1];
        }
        return params;
    },
};

elLaunchService.wrappedJSObject = elLaunchService;


var elLaunchServiceModule = {
    registerSelf: function(compMgr, fileSpec, location, type)
    {
        compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
        compMgr.registerFactoryLocation(CID,
                                    CLASSNAME,
                                    CONTRACTID,
                                    fileSpec,
                                    location,
                                    type);

        var catMgr = Components.classes["@mozilla.org/categorymanager;1"].getService(Components.interfaces.nsICategoryManager);

        catMgr.addCategoryEntry("app-startup", CLASSNAME, CONTRACTID, true, true);
        catMgr.addCategoryEntry("content-policy", CONTRACTID, CONTRACTID, true, true);
    },
    unregisterSelf: function(compMgr, fileSpec, location)
    {
        compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
        compMgr.unregisterFactoryLocation(CID, fileSpec);
        var catman = Components.classes["@mozilla.org/categorymanager;1"].getService(Components.interfaces.nsICategoryManager);
        catman.deleteCategoryEntry("app-startup", CONTRACTID, true);
    },
    getClassObject: function(compMgr, cid, iid)
    {
        if (!cid.equals(CID)) throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
        if (!iid.equals(Components.interfaces.nsIFactory)) throw Components.results.NS_ERROR_NO_INTERFACE;

        return elLaunchServiceFactory;
    },
    canUnload: function(compMgr)
    {
        return true;
    }
};

var elLaunchServiceFactory = {
    createInstance: function(outer, iid)
    {
        if (outer != null) throw Components.results.NS_ERROR_NO_AGGREGATION;

        return elLaunchService;
    }
};

function NSGetModule(compMgr, fileSpec)
{
    return elLaunchServiceModule;
}
